//
// Copyright (C) 2005 Andras Varga
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//

#include <fstream>
#include <sstream>

#include "inet/mobility/single/MyDynamicMotionFileCache.h"

namespace inet {

const MyDynamicMotionFile::Line *MyDynamicMotionFile::getLine(int nodeId) const
{
    LineList::const_iterator it = lines.begin();
    for (int i = 0; i < nodeId && it != lines.end(); i++)
        it++;
    //MyDynamicMotionFileCache::getInstance(0)->checkAndSet(nodeId);
    return (it == lines.end()) ? nullptr : &(*it);
}

MyDynamicMotionFileCache *MyDynamicMotionFileCache::inst;

MyDynamicMotionFileCache *MyDynamicMotionFileCache::getInstance(int hostNum)
{
    if (!inst){
        inst = new MyDynamicMotionFileCache;
        inst->counter = hostNum;
        inst->hostnums = hostNum;
    }
    return inst;
}

void MyDynamicMotionFileCache::deleteInstance()
{
    if (inst) {
        delete inst;
        inst = nullptr;
    }
}

 void MyDynamicMotionFileCache::checkAndSet(int nodeId)
 {
     counter--;
     if(counter == 0){
         cache.clear();
         counter = hostnums;
     }
     else if(counter < 0){
         throw cRuntimeError("Node: %d --Invalid access times: %d ", nodeId, counter);
     }
 }

const MyDynamicMotionFile *MyDynamicMotionFileCache::getFile(const char *filename)
{
    // load and store in cache
    if(counter == 0){
        cache.clear();
        counter = hostnums;
    }
    else if(counter < 0){
        throw cRuntimeError("Invalid access times: %d ", counter);
    }

    // if found, return it from cache
    auto it = cache.find(std::string(filename));
    if (it != cache.end() && counter > 0){
        counter--;
        EV << "Read from cache! Remained "<< counter << " hosts not read yet." << endl;
        return &(it->second);
    }

    MyDynamicMotionFile& mdFile = cache[filename];
    parseFile(filename, mdFile);
    counter--;
    EV << "Read from cache! Remained "<< counter << " hosts not read yet." << endl;
    return &mdFile;
}

void MyDynamicMotionFileCache::parseFile(const char *filename, MyDynamicMotionFile& mdFile)
{
    std::ifstream in(filename, std::ios::in);
    if (in.fail())
        throw cRuntimeError("Cannot open file '%s'", filename);

    std::string line;
    EV << "Read from File!" << endl;
    while (std::getline(in, line)) {
        mdFile.lines.push_back(MyDynamicMotionFile::Line());
        MyDynamicMotionFile::Line& vec = mdFile.lines.back();

        std::stringstream linestream(line);
        double d;
        while (linestream >> d)
            vec.push_back(d);
    }
    in.close();
}

} // namespace inet

